<!DOCTYPE HTML>
<html lang="zh-CN">


<head>
    <meta charset="utf-8">
    <meta name="keywords" content="mall项目部署, Lemonade&#39;s Blog">
    <meta name="description" content="文档地址
http://www.macrozheng.com/#/
写在前面项目简介mall项目是一套电商系统，包括前台商城系统及后台管理系统，基于SpringBoot+MyBatis实现，采用Docker容器化部署。
前台商城系统包含首页">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <meta name="renderer" content="webkit|ie-stand|ie-comp">
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="format-detection" content="telephone=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <meta name="referrer" content="no-referrer-when-downgrade">
    <!-- Global site tag (gtag.js) - Google Analytics -->


    <title>mall项目部署 | Lemonade&#39;s Blog</title>
    <link rel="icon" type="image/png" href="https://notes2021.oss-cn-beijing.aliyuncs.com/2021/IMG_0551.JPG">

    <link rel="stylesheet" type="text/css" href="/libs/awesome/css/all.min.css">
    <link rel="stylesheet" type="text/css" href="/libs/materialize/materialize.min.css">
    <link rel="stylesheet" type="text/css" href="/libs/aos/aos.css">
    <link rel="stylesheet" type="text/css" href="/libs/animate/animate.min.css">
    <link rel="stylesheet" type="text/css" href="/libs/lightGallery/css/lightgallery.min.css">
    <link rel="stylesheet" type="text/css" href="/css/matery.css">
    <link rel="stylesheet" type="text/css" href="/css/my.css">

    <script src="/libs/jquery/jquery-3.6.0.min.js"></script>

<meta name="generator" content="Hexo 6.0.0"><link rel="stylesheet" href="/css/prism-tomorrow.css" type="text/css"></head>




<body>
    <header class="navbar-fixed">
    <nav id="headNav" class="bg-color nav-transparent">
        <div id="navContainer" class="nav-wrapper container">
            <div class="brand-logo">
                <a href="/" class="waves-effect waves-light">
                    
                    <span class="logo-span">Lemonade&#39;s Blog</span>
                </a>
            </div>
            

<a href="#" data-target="mobile-nav" class="sidenav-trigger button-collapse"><i class="fas fa-bars"></i></a>
<ul class="right nav-menu">
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/" class="waves-effect waves-light">
      
      <i class="fas fa-home" style="zoom: 0.6;"></i>
      
      <span>首页</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/tags" class="waves-effect waves-light">
      
      <i class="fas fa-tags" style="zoom: 0.6;"></i>
      
      <span>标签</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/categories" class="waves-effect waves-light">
      
      <i class="fas fa-bookmark" style="zoom: 0.6;"></i>
      
      <span>分类</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/archives" class="waves-effect waves-light">
      
      <i class="fas fa-archive" style="zoom: 0.6;"></i>
      
      <span>归档</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/about" class="waves-effect waves-light">
      
      <i class="fas fa-user-circle" style="zoom: 0.6;"></i>
      
      <span>关于</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/contact" class="waves-effect waves-light">
      
      <i class="fas fa-comments" style="zoom: 0.6;"></i>
      
      <span>留言板</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/friends" class="waves-effect waves-light">
      
      <i class="fas fa-address-book" style="zoom: 0.6;"></i>
      
      <span>友情链接</span>
    </a>
    
  </li>
  
  <li>
    <a href="#searchModal" class="modal-trigger waves-effect waves-light">
      <i id="searchIcon" class="fas fa-search" title="搜索" style="zoom: 0.85;"></i>
    </a>
  </li>
</ul>


<div id="mobile-nav" class="side-nav sidenav">

    <div class="mobile-head bg-color">
        
        <div class="logo-name">Lemonade&#39;s Blog</div>
        <div class="logo-desc">
            
            Never really desperate, only the lost of the soul.
            
        </div>
    </div>

    <ul class="menu-list mobile-menu-list">
        
        <li class="m-nav-item">
	  
		<a href="/" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-home"></i>
			
			首页
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/tags" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-tags"></i>
			
			标签
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/categories" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-bookmark"></i>
			
			分类
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/archives" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-archive"></i>
			
			归档
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/about" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-user-circle"></i>
			
			关于
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/contact" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-comments"></i>
			
			留言板
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/friends" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-address-book"></i>
			
			友情链接
		</a>
          
        </li>
        
        
        <li><div class="divider"></div></li>
        <li>
            <a href="https://github.com/blinkfox/hexo-theme-matery" class="waves-effect waves-light" target="_blank">
                <i class="fab fa-github-square fa-fw"></i>Fork Me
            </a>
        </li>
        
    </ul>
</div>


        </div>

        
            <style>
    .nav-transparent .github-corner {
        display: none !important;
    }

    .github-corner {
        position: absolute;
        z-index: 10;
        top: 0;
        right: 0;
        border: 0;
        transform: scale(1.1);
    }

    .github-corner svg {
        color: #0f9d58;
        fill: #fff;
        height: 64px;
        width: 64px;
    }

    .github-corner:hover .octo-arm {
        animation: a 0.56s ease-in-out;
    }

    .github-corner .octo-arm {
        animation: none;
    }

    @keyframes a {
        0%,
        to {
            transform: rotate(0);
        }
        20%,
        60% {
            transform: rotate(-25deg);
        }
        40%,
        80% {
            transform: rotate(10deg);
        }
    }
</style>

<a href="https://github.com/blinkfox/hexo-theme-matery" class="github-corner tooltipped hide-on-med-and-down" target="_blank"
   data-tooltip="Fork Me" data-position="left" data-delay="50">
    <svg viewBox="0 0 250 250" aria-hidden="true">
        <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
        <path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
              fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>
        <path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
              fill="currentColor" class="octo-body"></path>
    </svg>
</a>
        
    </nav>

</header>

    



<div class="bg-cover pd-header post-cover" style="background-image: url('/medias/featureimages/19.jpg')">
    <div class="container" style="right: 0px;left: 0px;">
        <div class="row">
            <div class="col s12 m12 l12">
                <div class="brand">
                    <h1 class="description center-align post-title">mall项目部署</h1>
                </div>
            </div>
        </div>
    </div>
</div>




<main class="post-container content">

    
    <link rel="stylesheet" href="/libs/tocbot/tocbot.css">
<style>
    #articleContent h1::before,
    #articleContent h2::before,
    #articleContent h3::before,
    #articleContent h4::before,
    #articleContent h5::before,
    #articleContent h6::before {
        display: block;
        content: " ";
        height: 100px;
        margin-top: -100px;
        visibility: hidden;
    }

    #articleContent :focus {
        outline: none;
    }

    .toc-fixed {
        position: fixed;
        top: 64px;
    }

    .toc-widget {
        width: 345px;
        padding-left: 20px;
    }

    .toc-widget .toc-title {
        padding: 35px 0 15px 17px;
        font-size: 1.5rem;
        font-weight: bold;
        line-height: 1.5rem;
    }

    .toc-widget ol {
        padding: 0;
        list-style: none;
    }

    #toc-content {
        padding-bottom: 30px;
        overflow: auto;
    }

    #toc-content ol {
        padding-left: 10px;
    }

    #toc-content ol li {
        padding-left: 10px;
    }

    #toc-content .toc-link:hover {
        color: #42b983;
        font-weight: 700;
        text-decoration: underline;
    }

    #toc-content .toc-link::before {
        background-color: transparent;
        max-height: 25px;

        position: absolute;
        right: 23.5vw;
        display: block;
    }

    #toc-content .is-active-link {
        color: #42b983;
    }

    #floating-toc-btn {
        position: fixed;
        right: 15px;
        bottom: 76px;
        padding-top: 15px;
        margin-bottom: 0;
        z-index: 998;
    }

    #floating-toc-btn .btn-floating {
        width: 48px;
        height: 48px;
    }

    #floating-toc-btn .btn-floating i {
        line-height: 48px;
        font-size: 1.4rem;
    }
</style>
<div class="row">
    <div id="main-content" class="col s12 m12 l9">
        <!-- 文章内容详情 -->
<div id="artDetail">
    <div class="card">
        <div class="card-content article-info">
            <div class="row tag-cate">
                <div class="col s7">
                    
                    <div class="article-tag">
                        
                            <a href="/tags/%E9%A1%B9%E7%9B%AE%E4%B8%80/">
                                <span class="chip bg-color">项目一</span>
                            </a>
                        
                    </div>
                    
                </div>
                <div class="col s5 right-align">
                    
                    <div class="post-cate">
                        <i class="fas fa-bookmark fa-fw icon-category"></i>
                        
                            <a href="/categories/7-%E9%A1%B9%E7%9B%AE%E4%B8%80mall/" class="post-category">
                                7.项目一mall
                            </a>
                        
                    </div>
                    
                </div>
            </div>

            <div class="post-info">
                
                <div class="post-date info-break-policy">
                    <i class="far fa-calendar-minus fa-fw"></i>发布日期:&nbsp;&nbsp;
                    2022-01-15
                </div>
                

                
                <div class="post-date info-break-policy">
                    <i class="far fa-calendar-check fa-fw"></i>更新日期:&nbsp;&nbsp;
                    2022-01-20
                </div>
                

                
                <div class="info-break-policy">
                    <i class="far fa-file-word fa-fw"></i>文章字数:&nbsp;&nbsp;
                    4.8k
                </div>
                

                
                <div class="info-break-policy">
                    <i class="far fa-clock fa-fw"></i>阅读时长:&nbsp;&nbsp;
                    19 分
                </div>
                

                
                    <div id="busuanzi_container_page_pv" class="info-break-policy">
                        <i class="far fa-eye fa-fw"></i>阅读次数:&nbsp;&nbsp;
                        <span id="busuanzi_value_page_pv"></span>
                    </div>
				
            </div>
        </div>
        <hr class="clearfix">

        

        

        <div class="card-content article-card-content">
            <div id="articleContent">
                <p>文档地址</p>
<p><a target="_blank" rel="noopener" href="http://www.macrozheng.com/#/">http://www.macrozheng.com/#/</a></p>
<h1 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h1><h2 id="项目简介"><a href="#项目简介" class="headerlink" title="项目简介"></a>项目简介</h2><p>mall项目是一套电商系统，包括前台商城系统及后台管理系统，基于SpringBoot+MyBatis实现，采用Docker容器化部署。</p>
<p>前台商城系统包含首页门户、商品推荐、商品搜索、商品展示、购物车、订单流程、会员中心、客户服务、帮助中心等模块。</p>
<p>后台管理系统包含商品管理、订单管理、会员管理、促销管理、运营管理、内容管理、统计报表、财务管理、权限管理、设置等模块。</p>
<pre><code>mall
├── mall-common -- 工具类及通用代码
├── mall-mbg -- MyBatisGenerator生成的数据库操作代码
├── mall-security -- SpringSecurity封装公用模块
├── mall-admin -- 后台商城管理系统接口
├── mall-search -- 基于Elasticsearch的商品搜索系统
├── mall-portal -- 前台商城系统接口
└── mall-demo -- 框架搭建时的测试代码
</code></pre>
<h2 id="项目演示"><a href="#项目演示" class="headerlink" title="项目演示"></a>项目演示</h2><ul>
<li><p>后台项目演示：<a target="_blank" rel="noopener" href="http://www.macrozheng.com/admin/index.html">http://www.macrozheng.com/admin/index.html</a></p>
</li>
<li><p>移动端项目演示：<a target="_blank" rel="noopener" href="http://www.macrozheng.com/app/index.html">http://www.macrozheng.com/app/index.html</a></p>
</li>
</ul>
<h2 id="mall中使用的技术"><a href="#mall中使用的技术" class="headerlink" title="mall中使用的技术"></a>mall中使用的技术</h2><blockquote>
<p>mall采用现阶段主流技术实现，涵盖了一般项目中几乎所有使用的技术。</p>
</blockquote>
<table>
<thead>
<tr>
<th>技术</th>
<th>版本</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>Spring Boot</td>
<td>2.3.0</td>
<td>容器+MVC框架</td>
</tr>
<tr>
<td>Spring Security</td>
<td>5.1.4</td>
<td>认证和授权框架</td>
</tr>
<tr>
<td>MyBatis</td>
<td>3.4.6</td>
<td>ORM框架</td>
</tr>
<tr>
<td>MyBatisGenerator</td>
<td>1.3.3</td>
<td>数据层代码生成</td>
</tr>
<tr>
<td>PageHelper</td>
<td>5.1.8</td>
<td>MyBatis物理分页插件</td>
</tr>
<tr>
<td>Swagger-UI</td>
<td>2.9.2</td>
<td>文档生产工具</td>
</tr>
<tr>
<td>Elasticsearch</td>
<td>7.6.2</td>
<td>搜索引擎</td>
</tr>
<tr>
<td>RabbitMq</td>
<td>3.7.14</td>
<td>消息队列</td>
</tr>
<tr>
<td>Redis</td>
<td>5.0</td>
<td>分布式缓存</td>
</tr>
<tr>
<td>MongoDb</td>
<td>4.2.5</td>
<td>NoSql数据库</td>
</tr>
<tr>
<td>Docker</td>
<td>18.09.0</td>
<td>应用容器引擎</td>
</tr>
<tr>
<td>Druid</td>
<td>1.1.10</td>
<td>数据库连接池</td>
</tr>
<tr>
<td>OSS</td>
<td>2.5.0</td>
<td>对象存储</td>
</tr>
<tr>
<td>JWT</td>
<td>0.9.0</td>
<td>JWT登录支持</td>
</tr>
<tr>
<td>Lombok</td>
<td>1.18.6</td>
<td>简化对象封装工具</td>
</tr>
</tbody></table>
<h2 id="mall实现的功能概览"><a href="#mall实现的功能概览" class="headerlink" title="mall实现的功能概览"></a>mall实现的功能概览</h2><ul>
<li>商品模块<ul>
<li>商品管理</li>
<li>商品分类管理</li>
<li>商品类型管理</li>
<li>品牌管理</li>
</ul>
</li>
<li>订单模块<ul>
<li>订单管理</li>
<li>订单设置</li>
<li>退货申请处理</li>
<li>退货原因设置</li>
</ul>
</li>
<li>营销模块<ul>
<li>秒杀活动管理</li>
<li>优惠价管理</li>
<li>品牌推荐管理</li>
<li>新品推荐管理</li>
<li>人气推荐管理</li>
<li>专题推荐管理</li>
<li>首页广告管理</li>
</ul>
</li>
</ul>
<h2 id="mall数据库表概览"><a href="#mall数据库表概览" class="headerlink" title="mall数据库表概览"></a>mall数据库表概览</h2><blockquote>
<p>mall项目目前有71张数据表，业务逻辑有一定复杂度，平时做项目参考也够了。</p>
</blockquote>
<p><img src="https://notes2021.oss-cn-beijing.aliyuncs.com/2021/mall_mysql_all.png"></p>
<p><img src="https://notes2021.oss-cn-beijing.aliyuncs.com/2021/image-20220116114951356.png"></p>
<h3 id="数据库表前缀说明"><a href="#数据库表前缀说明" class="headerlink" title="数据库表前缀说明"></a>数据库表前缀说明</h3><ul>
<li>cms_*：内容管理模块相关表</li>
<li>oms_*：订单管理模块相关表</li>
<li>pms_*：商品模块相关表</li>
<li>sms_*：营销模块相关表</li>
<li>ums_*：会员模块相关表</li>
</ul>
<h2 id="学习所需知识点"><a href="#学习所需知识点" class="headerlink" title="学习所需知识点"></a>学习所需知识点</h2><blockquote>
<p>由于mall项目涉及到很多知识点，比如SpringBoot、ElasticSearch、Redis、Mongodb等，本教程不会详细讲述这些，只会讲述本项目相关部分，所以推荐以下资料。对其中一些知识点并不熟悉的同学，可以看下下面推荐的资料。</p>
</blockquote>
<h3 id="IDEA"><a href="#IDEA" class="headerlink" title="IDEA"></a>IDEA</h3><p>《IntelliJ-IDEA-Tutorial》：<a target="_blank" rel="noopener" href="https://github.com/judasn/IntelliJ-IDEA-Tutorial">https://github.com/judasn/IntelliJ-IDEA-Tutorial</a></p>
<blockquote>
<p>特别全的IDEA使用教程，可以学到很多实用的技巧。</p>
</blockquote>
<h3 id="Spring"><a href="#Spring" class="headerlink" title="Spring"></a>Spring</h3><p>《Spring实战（第4版）》：<a target="_blank" rel="noopener" href="https://book.douban.com/subject/26767354/">https://book.douban.com/subject/26767354/</a></p>
<blockquote>
<p>经典的、畅销的Spring学习和实践指南,从此书可以学习到Spring的实用用法，对Spring有个整体的了解，推荐整本阅读。</p>
</blockquote>
<h3 id="SpringBoot"><a href="#SpringBoot" class="headerlink" title="SpringBoot"></a>SpringBoot</h3><p>《Spring Boot实战》：<a target="_blank" rel="noopener" href="https://book.douban.com/subject/26857423/">https://book.douban.com/subject/26857423/</a></p>
<blockquote>
<p>SpringBoot的入门书，一共也就200多页，反正我是看完了，其中关于Groovy和Grails部分大可不看。</p>
</blockquote>
<h3 id="MyBatis"><a href="#MyBatis" class="headerlink" title="MyBatis"></a>MyBatis</h3><p>《MyBatis从入门到精通》：<a target="_blank" rel="noopener" href="https://book.douban.com/subject/27074809/">https://book.douban.com/subject/27074809/</a></p>
<blockquote>
<p>很好的一本MyBatis入门书，作者是开源插件PageHelper的项目主，平时忘了MyBatis的一些用法的时候可以当工具书使用，推荐整本阅读</p>
</blockquote>
<h3 id="MySQL"><a href="#MySQL" class="headerlink" title="MySQL"></a>MySQL</h3><p>《深入浅出MySQL》：<a target="_blank" rel="noopener" href="https://book.douban.com/subject/25817684/">https://book.douban.com/subject/25817684/</a></p>
<blockquote>
<p>网易DBA写的一本MySql书籍，作为一个开发者，我们只要看第一部分基础篇、第二部分开发篇、第三部分优化篇即可。</p>
</blockquote>
<h3 id="Linux"><a href="#Linux" class="headerlink" title="Linux"></a>Linux</h3><p>《循序渐进Linux（第2版）》：<a target="_blank" rel="noopener" href="https://book.douban.com/subject/26758194/">https://book.douban.com/subject/26758194/</a></p>
<blockquote>
<p>南非蚂蚁写的一本Linux书籍，作为一个开发者，我们只要看第一篇基础知识篇、第二篇服务器搭建篇即可，后面讲到生产环境部署项目会用到。</p>
</blockquote>
<h3 id="Elasticsearch"><a href="#Elasticsearch" class="headerlink" title="Elasticsearch"></a>Elasticsearch</h3><p>《Elasticsearch 权威指南》：<a target="_blank" rel="noopener" href="https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html">https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html</a></p>
<blockquote>
<p>Elasticsearch官方推荐的中文学习资料，基于Elasticsearch2.4.x版本，比较老，但是可堪一用。大多数成熟的框架，版本迭代用法相差不会很大。</p>
</blockquote>
<p>《Elasticsearch 技术解析与实战》：<a target="_blank" rel="noopener" href="https://book.douban.com/subject/26967826/">https://book.douban.com/subject/26967826/</a></p>
<blockquote>
<p>如果你觉得上面那本ElasticSearch版本太老的话可以看这本。</p>
</blockquote>
<h3 id="MongoDB"><a href="#MongoDB" class="headerlink" title="MongoDB"></a>MongoDB</h3><p>《MongoDB实战(第二版)》：<a target="_blank" rel="noopener" href="https://book.douban.com/subject/27061123/">https://book.douban.com/subject/27061123/</a></p>
<blockquote>
<p>很好的一本MongoDB实战书，作者参与过MongoDB的驱动开发，感兴趣的可以都看下。</p>
</blockquote>
<h3 id="Docker"><a href="#Docker" class="headerlink" title="Docker"></a>Docker</h3><p>《Spring Cloud与Docker微服务架构实战》：<a target="_blank" rel="noopener" href="https://book.douban.com/subject/27028228/">https://book.douban.com/subject/27028228/</a></p>
<blockquote>
<p>我们只需要看下这本书的Docker部分即可，后面讲到生产环境部署项目会用到。</p>
</blockquote>
<h3 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h3><blockquote>
<p> 如果你按照我的推荐看了以上部分的资料，或者你已经有了以上部分的基础，那么你学习mall的时候会非常顺利。</p>
</blockquote>
<h1 id="部署"><a href="#部署" class="headerlink" title="部署"></a>部署</h1><h2 id="在Windows环境下部署"><a href="#在Windows环境下部署" class="headerlink" title="在Windows环境下部署"></a>在Windows环境下部署</h2><blockquote>
<p>主要包括IDEA、Mysql、Redis、Mongodb、RabbitMQ、Elasticsearch、Logstash、Kibana、OSS。</p>
</blockquote>
<h2 id="在Linux环境下部署（基于Docker容器）"><a href="#在Linux环境下部署（基于Docker容器）" class="headerlink" title="在Linux环境下部署（基于Docker容器）"></a>在Linux环境下部署（基于Docker容器）</h2><blockquote>
<p>涉及在Docker容器中安装MySQL、Redis、Nginx、RabbitMQ、MongoDB、Elasticsearch、Logstash、Kibana，以及SpringBoot应用部署，基于<code>CenterOS7.6</code>。</p>
</blockquote>
<h2 id="在Linux环境下部署（基于Docker-Compose容器）"><a href="#在Linux环境下部署（基于Docker-Compose容器）" class="headerlink" title="在Linux环境下部署（基于Docker Compose容器）"></a>在Linux环境下部署（基于Docker Compose容器）</h2><blockquote>
<p>最简单的mall在Linux下部署方式，使用两个Docker Compose脚本即可完成部署。第一个脚本用于部署mall运行所依赖的服务（MySQL、Redis、Nginx、RabbitMQ、MongoDB、Elasticsearch、Logstash、Kibana），第二个脚本用于部署mall中的应用（mall-admin、mall-search、mall-portal）。</p>
</blockquote>
<h3 id="docker环境搭建及使用"><a href="#docker环境搭建及使用" class="headerlink" title="docker环境搭建及使用"></a>docker环境搭建及使用</h3><p>具体参考：开发者必备Docker命令</p>
<blockquote>
<p>主要讲解Docker环境的安装以及Docker常用命令的使用，掌握这些对Docker环境下应用的部署具有很大帮助。</p>
</blockquote>
<h4 id="Docker简介"><a href="#Docker简介" class="headerlink" title="Docker简介"></a>Docker简介</h4><p>Docker 是一个开源的应用容器引擎，让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中，然后发布到任何流行的 Linux或Windows机器上。使用Docker可以更方便地打包、测试以及部署应用程序。</p>
<h4 id="Docker环境安装"><a href="#Docker环境安装" class="headerlink" title="Docker环境安装"></a>Docker环境安装</h4><ul>
<li>安装yum-utils：</li>
</ul>
<pre class=" language-bash"><code class="language-bash">yum <span class="token function">install</span> -y yum-utils device-mapper-persistent-data lvm2
</code></pre>
<ul>
<li>为yum源添加docker仓库位置：</li>
</ul>
<pre class=" language-bash"><code class="language-bash">yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
<span class="token comment" spellcheck="true"># 也可以使用下面阿里云的</span>
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
</code></pre>
<ul>
<li>安装docker:</li>
</ul>
<pre class=" language-bash"><code class="language-bash">yum <span class="token function">install</span> docker-ce
</code></pre>
<ul>
<li>启动docker:</li>
</ul>
<pre class=" language-bash"><code class="language-bash">systemctl start docker
</code></pre>
<h4 id="Docker镜像常用命令"><a href="#Docker镜像常用命令" class="headerlink" title="Docker镜像常用命令"></a>Docker镜像常用命令</h4><h5 id="下载镜像"><a href="#下载镜像" class="headerlink" title="下载镜像"></a>下载镜像</h5><pre class=" language-sh"><code class="language-sh">docker pull java:8
</code></pre>
<h5 id="列出镜像"><a href="#列出镜像" class="headerlink" title="列出镜像"></a>列出镜像</h5><pre class=" language-sh"><code class="language-sh">docker images
</code></pre>
<h5 id="删除镜像"><a href="#删除镜像" class="headerlink" title="删除镜像"></a>删除镜像</h5><pre class=" language-sh"><code class="language-sh"># 指定名称删除镜像
docker rmi java:8
# 指定名称删除镜像（强制）
docker rmi -f java:8
# 强制删除所有镜像
docker rmi -f $(docker images)
</code></pre>
<h4 id="Docker容器常用命令"><a href="#Docker容器常用命令" class="headerlink" title="Docker容器常用命令"></a>Docker容器常用命令</h4><h5 id="新建并启动容器"><a href="#新建并启动容器" class="headerlink" title="新建并启动容器"></a>新建并启动容器</h5><pre class=" language-sh"><code class="language-sh">docker run -p 80:80 --name nginx -d nginx:1.17.0
</code></pre>
<pre class=" language-sh"><code class="language-sh"># Docker run命令参数整理
Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]       
    -d, --detach=false         指定容器运行于前台还是后台，默认为false
    -m, --memory=""            指定容器的内存上限 
    -P, --publish-all=false    指定容器暴露的端口
    -h, --hostname=""          指定容器的主机名
    -v, --volume=[]            给容器挂载存储卷，挂载到容器的某个目录
    --entrypoint=""            覆盖image的入口点
    --name=""                  指定容器名字，后续可以通过名字进行容器管理，links特性需要使用名字  
    --restart="no"             指定容器停止后的重启策略: 
                                no：容器退出时不重启   
                                on-failure：容器故障退出（返回值非零）时重启  
                                always：容器退出时总是重启  
</code></pre>
<h5 id="列出容器"><a href="#列出容器" class="headerlink" title="列出容器"></a>列出容器</h5><pre class=" language-sh"><code class="language-sh"># 列出运行中的容器
docker ps
# 列出所有容器
docker ps -a
</code></pre>
<h5 id="停止容器"><a href="#停止容器" class="headerlink" title="停止容器"></a>停止容器</h5><pre class=" language-sh"><code class="language-sh"># $ContainerName及$ContainerId可以用docker ps命令查询出来
docker stop $ContainerName(或者$ContainerId)
</code></pre>
<p>比如：</p>
<pre class=" language-sh"><code class="language-sh">docker stop nginx
#或者
docker stop c5f5d5125587
</code></pre>
<h5 id="进入容器"><a href="#进入容器" class="headerlink" title="进入容器"></a>进入容器</h5><ul>
<li>先查询出容器的pid：</li>
</ul>
<pre class=" language-bash"><code class="language-bash">docker inspect --format <span class="token string">"{{.State.Pid}}"</span> <span class="token variable">$ContainerName</span><span class="token punctuation">(</span>或者<span class="token variable">$ContainerId</span><span class="token punctuation">)</span>
</code></pre>
<ul>
<li>根据容器的pid进入容器：</li>
</ul>
<pre class=" language-bash"><code class="language-bash">nsenter --target <span class="token string">"<span class="token variable">$pid</span>"</span> --mount --uts --ipc --net --pid
</code></pre>
<h5 id="删除容器"><a href="#删除容器" class="headerlink" title="删除容器"></a>删除容器</h5><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 删除指定容器：</span>
docker <span class="token function">rm</span> <span class="token variable">$ContainerName</span><span class="token punctuation">(</span>或者<span class="token variable">$ContainerId</span><span class="token punctuation">)</span>
<span class="token comment" spellcheck="true"># 强制删除所有容器</span>
docker <span class="token function">rm</span> -f <span class="token variable"><span class="token variable">$(</span>docker <span class="token function">ps</span> -a -q<span class="token variable">)</span></span>
</code></pre>
<h5 id="查看容器的日志"><a href="#查看容器的日志" class="headerlink" title="查看容器的日志"></a>查看容器的日志</h5><pre class=" language-sh"><code class="language-sh"># 查看当前全部日志
docker logs $ContainerName(或者$ContainerId)
# 动态查看
docker logs $ContainerName(或者$ContainerId) -f
</code></pre>
<h5 id="在宿主机查看docker使用cpu、内存、网络、io情况"><a href="#在宿主机查看docker使用cpu、内存、网络、io情况" class="headerlink" title="在宿主机查看docker使用cpu、内存、网络、io情况"></a>在宿主机查看docker使用cpu、内存、网络、io情况</h5><pre class=" language-sh"><code class="language-sh"># 查看指定容器情况：
docker stats $ContainerName(或者$ContainerId)
# 查看所有容器情况：
docker stats -a
</code></pre>
<h5 id="查看Docker磁盘使用情况"><a href="#查看Docker磁盘使用情况" class="headerlink" title="查看Docker磁盘使用情况"></a>查看Docker磁盘使用情况</h5><pre class=" language-sh"><code class="language-sh">docker system df
</code></pre>
<h5 id="进入Docker容器内部的bash"><a href="#进入Docker容器内部的bash" class="headerlink" title="进入Docker容器内部的bash"></a>进入Docker容器内部的bash</h5><pre class=" language-sh"><code class="language-sh">docker exec -it $ContainerName /bin/bash
</code></pre>
<h4 id="修改Docker镜像的存放位置"><a href="#修改Docker镜像的存放位置" class="headerlink" title="修改Docker镜像的存放位置"></a>修改Docker镜像的存放位置</h4><h5 id="查看Docker镜像的存放位置："><a href="#查看Docker镜像的存放位置：" class="headerlink" title="查看Docker镜像的存放位置："></a>查看Docker镜像的存放位置：</h5><pre class=" language-sh"><code class="language-sh">docker info | grep "Docker Root Dir"
</code></pre>
<h5 id="关闭Docker服务："><a href="#关闭Docker服务：" class="headerlink" title="关闭Docker服务："></a>关闭Docker服务：</h5><pre class=" language-bash"><code class="language-bash">systemctl stop docker
</code></pre>
<h5 id="移动目录到目标路径："><a href="#移动目录到目标路径：" class="headerlink" title="移动目录到目标路径："></a>移动目录到目标路径：</h5><pre class=" language-bash"><code class="language-bash"><span class="token function">mv</span> /var/lib/docker /mydata/docker
</code></pre>
<h5 id="建立软连接："><a href="#建立软连接：" class="headerlink" title="建立软连接："></a>建立软连接：</h5><pre class=" language-bash"><code class="language-bash"><span class="token function">ln</span> -s /mydata/docker /var/lib/docker
</code></pre>
<h3 id="docker-compose环境搭建及使用"><a href="#docker-compose环境搭建及使用" class="headerlink" title="docker-compose环境搭建及使用"></a>docker-compose环境搭建及使用</h3><p>具体参考：使用Docker Compose部署SpringBoot应用</p>
<blockquote>
<p>Docker Compose是一个用于定义和运行多个docker容器应用的工具。使用Compose你可以用YAML文件来配置你的应用服务，然后使用一个命令，你就可以部署你配置的所有服务了。</p>
</blockquote>
<h4 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h4><h5 id="下载Docker-Compose"><a href="#下载Docker-Compose" class="headerlink" title="下载Docker Compose"></a>下载Docker Compose</h5><pre class=" language-sh"><code class="language-sh">curl -L https://get.daocloud.io/docker/compose/releases/download/1.24.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
</code></pre>
<h5 id="修改该文件的权限为可执行"><a href="#修改该文件的权限为可执行" class="headerlink" title="修改该文件的权限为可执行"></a>修改该文件的权限为可执行</h5><pre class=" language-sh"><code class="language-sh">chmod +x /usr/local/bin/docker-compose
</code></pre>
<h5 id="查看是否已经安装成功"><a href="#查看是否已经安装成功" class="headerlink" title="查看是否已经安装成功"></a>查看是否已经安装成功</h5><pre class=" language-sh"><code class="language-sh">docker-compose --version
</code></pre>
<h4 id="使用Docker-Compose的步骤"><a href="#使用Docker-Compose的步骤" class="headerlink" title="使用Docker Compose的步骤"></a>使用Docker Compose的步骤</h4><ul>
<li>使用Dockerfile定义应用程序环境，一般需要修改初始镜像行为时才需要使用；</li>
<li>使用docker-compose.yml定义需要部署的应用程序服务，以便执行脚本一次性部署；</li>
<li>使用docker-compose up命令将所有应用服务一次性部署起来。</li>
</ul>
<h4 id="docker-compose-yml常用命令"><a href="#docker-compose-yml常用命令" class="headerlink" title="docker-compose.yml常用命令"></a>docker-compose.yml常用命令</h4><h5 id="image"><a href="#image" class="headerlink" title="image"></a>image</h5><blockquote>
<p>指定运行的镜像名称</p>
</blockquote>
<pre class=" language-yaml"><code class="language-yaml"><span class="token comment" spellcheck="true"># 运行的是mysql5.7的镜像</span>
<span class="token key atrule">image</span><span class="token punctuation">:</span> mysql<span class="token punctuation">:</span><span class="token number">5.7</span>
</code></pre>
<h5 id="container-name"><a href="#container-name" class="headerlink" title="container_name"></a>container_name</h5><blockquote>
<p>配置容器名称</p>
</blockquote>
<pre class=" language-yaml"><code class="language-yaml"><span class="token comment" spellcheck="true"># 容器名称为mysql</span>
<span class="token key atrule">container_name</span><span class="token punctuation">:</span> mysql
</code></pre>
<h5 id="ports"><a href="#ports" class="headerlink" title="ports"></a>ports</h5><blockquote>
<p>指定宿主机和容器的端口映射（HOST:CONTAINER）</p>
</blockquote>
<pre class=" language-yaml"><code class="language-yaml"><span class="token comment" spellcheck="true"># 将宿主机的3306端口映射到容器的3306端口</span>
<span class="token key atrule">ports</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> 3306<span class="token punctuation">:</span><span class="token number">3306</span>
</code></pre>
<h5 id="volumes"><a href="#volumes" class="headerlink" title="volumes"></a>volumes</h5><blockquote>
<p>将宿主机的文件或目录挂载到容器中（HOST:CONTAINER）</p>
</blockquote>
<pre class=" language-yaml"><code class="language-yaml"><span class="token comment" spellcheck="true"># 将外部文件挂载到myql容器中</span>
<span class="token key atrule">volumes</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> /mydata/mysql/log<span class="token punctuation">:</span>/var/log/mysql
  <span class="token punctuation">-</span> /mydata/mysql/data<span class="token punctuation">:</span>/var/lib/mysql
  <span class="token punctuation">-</span> /mydata/mysql/conf<span class="token punctuation">:</span>/etc/mysql
</code></pre>
<h5 id="environment"><a href="#environment" class="headerlink" title="environment"></a>environment</h5><blockquote>
<p>配置环境变量</p>
</blockquote>
<pre class=" language-yaml"><code class="language-yaml"><span class="token comment" spellcheck="true"># 设置mysqlroot帐号密码的环境变量</span>
<span class="token key atrule">environment</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> MYSQL_ROOT_PASSWORD=root
</code></pre>
<h5 id="links"><a href="#links" class="headerlink" title="links"></a>links</h5><blockquote>
<p>连接其他容器的服务（SERVICE:ALIAS）</p>
</blockquote>
<pre class=" language-yaml"><code class="language-yaml"><span class="token comment" spellcheck="true"># 可以以database为域名访问服务名称为db的容器</span>
<span class="token key atrule">links</span><span class="token punctuation">:</span>
  <span class="token punctuation">-</span> db<span class="token punctuation">:</span>database
</code></pre>
<h4 id="Docker-Compose常用命令"><a href="#Docker-Compose常用命令" class="headerlink" title="Docker Compose常用命令"></a>Docker Compose常用命令</h4><h5 id="构建、创建、启动相关容器"><a href="#构建、创建、启动相关容器" class="headerlink" title="构建、创建、启动相关容器"></a>构建、创建、启动相关容器</h5><pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># -d表示在后台运行</span>
docker-compose up -d
</code></pre>
<h5 id="指定文件启动"><a href="#指定文件启动" class="headerlink" title="指定文件启动"></a>指定文件启动</h5><pre class=" language-bash"><code class="language-bash">docker-compose -f docker-compose.yml up -d
</code></pre>
<h5 id="停止所有相关容器"><a href="#停止所有相关容器" class="headerlink" title="停止所有相关容器"></a>停止所有相关容器</h5><pre class=" language-bash"><code class="language-bash">docker-compose stop
</code></pre>
<h5 id="列出所有容器信息"><a href="#列出所有容器信息" class="headerlink" title="列出所有容器信息"></a>列出所有容器信息</h5><pre class=" language-bash"><code class="language-bash">docker-compose <span class="token function">ps</span>
</code></pre>
<h4 id="使用Docker-Compose-部署应用"><a href="#使用Docker-Compose-部署应用" class="headerlink" title="使用Docker Compose 部署应用"></a>使用Docker Compose 部署应用</h4><h5 id="编写docker-compose-yml文件"><a href="#编写docker-compose-yml文件" class="headerlink" title="编写docker-compose.yml文件"></a>编写docker-compose.yml文件</h5><blockquote>
<p>Docker Compose将所管理的容器分为三层，工程、服务及容器。docker-compose.yml中定义所有服务组成了一个工程，services节点下即为服务，服务之下为容器。</p>
<p>容器与容器直之间可以以服务名称为域名进行访问，比如在mall-tiny-docker-compose服务中可以通过jdbc:mysql//db:3306这个地址来访问db这个mysql服务。</p>
</blockquote>
<pre class=" language-yaml"><code class="language-yaml"><span class="token key atrule">version</span><span class="token punctuation">:</span> <span class="token string">'3'</span>
<span class="token key atrule">services</span><span class="token punctuation">:</span>
  <span class="token comment" spellcheck="true"># 指定服务名称</span>
  <span class="token key atrule">db</span><span class="token punctuation">:</span>
    <span class="token comment" spellcheck="true"># 指定服务使用的镜像</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> mysql<span class="token punctuation">:</span><span class="token number">5.7</span>
    <span class="token comment" spellcheck="true"># 指定容器名称</span>
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> mysql
    <span class="token comment" spellcheck="true"># 指定服务运行的端口</span>
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> 3306<span class="token punctuation">:</span><span class="token number">3306</span>
    <span class="token comment" spellcheck="true"># 指定容器中需要挂载的文件</span>
    <span class="token key atrule">volumes</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> /mydata/mysql/log<span class="token punctuation">:</span>/var/log/mysql
      <span class="token punctuation">-</span> /mydata/mysql/data<span class="token punctuation">:</span>/var/lib/mysql
      <span class="token punctuation">-</span> /mydata/mysql/conf<span class="token punctuation">:</span>/etc/mysql
    <span class="token comment" spellcheck="true"># 指定容器的环境变量</span>
    <span class="token key atrule">environment</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> MYSQL_ROOT_PASSWORD=root
  <span class="token comment" spellcheck="true"># 指定服务名称</span>
  <span class="token key atrule">mall-tiny-docker-compose</span><span class="token punctuation">:</span>
    <span class="token comment" spellcheck="true"># 指定服务使用的镜像</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> mall<span class="token punctuation">-</span>tiny/mall<span class="token punctuation">-</span>tiny<span class="token punctuation">-</span>docker<span class="token punctuation">-</span>compose<span class="token punctuation">:</span>0.0.1<span class="token punctuation">-</span>SNAPSHOT
    <span class="token comment" spellcheck="true"># 指定容器名称</span>
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> mall<span class="token punctuation">-</span>tiny<span class="token punctuation">-</span>docker<span class="token punctuation">-</span>compose
    <span class="token comment" spellcheck="true"># 指定服务运行的端口</span>
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> 8080<span class="token punctuation">:</span><span class="token number">8080</span>
    <span class="token comment" spellcheck="true"># 指定容器中需要挂载的文件</span>
    <span class="token key atrule">volumes</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> /etc/localtime<span class="token punctuation">:</span>/etc/localtime
      <span class="token punctuation">-</span> /mydata/app/mall<span class="token punctuation">-</span>tiny<span class="token punctuation">-</span>docker<span class="token punctuation">-</span>compose/logs<span class="token punctuation">:</span>/var/logs
</code></pre>
<p><strong>注意：如果遇到mall-tiny-docker-compose服务无法连接到mysql，需要在mysql中建立mall数据库，同时导入mall.sql脚本。具体参考<a target="_blank" rel="noopener" href="https://mp.weixin.qq.com/s/U_OcNMpLAJJum_s9jbZLGg">使用Dockerfile为SpringBoot应用构建Docker镜像</a>中的运行mysql服务并设置部分。</strong></p>
<h5 id="使用maven插件构建mall-tiny-docker-compose镜像"><a href="#使用maven插件构建mall-tiny-docker-compose镜像" class="headerlink" title="使用maven插件构建mall-tiny-docker-compose镜像"></a>使用maven插件构建mall-tiny-docker-compose镜像</h5><h5 id="运行Docker-Compose命令启动所有服务"><a href="#运行Docker-Compose命令启动所有服务" class="headerlink" title="运行Docker Compose命令启动所有服务"></a>运行Docker Compose命令启动所有服务</h5><p>先将<code>docker-compose.yml</code>上传至Linux服务器，再在当前目录下运行如下命令：</p>
<pre class=" language-bash"><code class="language-bash">docker-compose up -d
</code></pre>
<h3 id="mall项目的docker-compose部署"><a href="#mall项目的docker-compose部署" class="headerlink" title="mall项目的docker-compose部署"></a>mall项目的docker-compose部署</h3><h4 id="运行配置要求"><a href="#运行配置要求" class="headerlink" title="运行配置要求"></a>运行配置要求</h4><p>CenterOS7.6版本，推荐4G以上内存。</p>
<h4 id="部署相关文件"><a href="#部署相关文件" class="headerlink" title="部署相关文件"></a>部署相关文件</h4><ul>
<li>数据库脚本<code>mall.sql</code>：<a target="_blank" rel="noopener" href="https://github.com/macrozheng/mall/blob/master/document/sql/mall.sql">https://github.com/macrozheng/mall/blob/master/document/sql/mall.sql</a></li>
<li>nginx配置文件<code>nginx.conf</code>：<a target="_blank" rel="noopener" href="https://github.com/macrozheng/mall/blob/master/document/docker/nginx.conf">https://github.com/macrozheng/mall/blob/master/document/docker/nginx.conf</a></li>
<li>Logstash配置文件<code>logstash.conf</code>：<a target="_blank" rel="noopener" href="https://github.com/macrozheng/mall/blob/master/document/elk/logstash.conf">https://github.com/macrozheng/mall/blob/master/document/elk/logstash.conf</a></li>
<li>系统服务运行脚本<code>docker-compose-env.yml</code>：<a target="_blank" rel="noopener" href="https://github.com/macrozheng/mall/tree/master/document/docker/docker-compose-env.yml">https://github.com/macrozheng/mall/tree/master/document/docker/docker-compose-env.yml</a></li>
<li>应用服务运行脚本<code>docker-compose-app.yml</code>：<a target="_blank" rel="noopener" href="https://github.com/macrozheng/mall/tree/master/document/docker/docker-compose-app.yml">https://github.com/macrozheng/mall/tree/master/document/docker/docker-compose-app.yml</a></li>
</ul>
<h4 id="部署前准备"><a href="#部署前准备" class="headerlink" title="部署前准备"></a>部署前准备</h4><h5 id="打包并上传mall应用的镜像"><a href="#打包并上传mall应用的镜像" class="headerlink" title="打包并上传mall应用的镜像"></a>打包并上传mall应用的镜像</h5><p>需要打包mall-admin、mall-search、mall-portal的docker镜像，具体参考：使用Maven插件为SpringBoot应用构建Docker镜像</p>
<blockquote>
<p>本文主要介绍如何使用Maven插件将SpringBoot应用打包为Docker镜像，并上传到私有镜像仓库Docker Registry的过程。</p>
</blockquote>
<pre class=" language-sh"><code class="language-sh">docker run -d -p 5001:5001 --restart=always --name registry2 registry:2
</code></pre>
<p><img src="https://notes2021.oss-cn-beijing.aliyuncs.com/2021/image-20220116012154107.png"></p>
<h5 id="下载所有需要安装的Docker镜像"><a href="#下载所有需要安装的Docker镜像" class="headerlink" title="下载所有需要安装的Docker镜像"></a>下载所有需要安装的Docker镜像</h5><pre class=" language-sh"><code class="language-sh">docker pull mysql:5.7
docker pull redis:5
docker pull nginx:1.10
docker pull rabbitmq:3.7.15-management
docker pull elasticsearch:7.6.2
docker pull kibana:7.6.2
docker pull logstash:7.6.2
docker pull mongo:4.2.5
</code></pre>
<h5 id="Elasticsearch-1"><a href="#Elasticsearch-1" class="headerlink" title="Elasticsearch"></a><a target="_blank" rel="noopener" href="http://www.macrozheng.com/#/deploy/mall_deploy_docker_compose?id=elasticsearch">Elasticsearch</a></h5><ul>
<li>需要设置系统内核参数，否则会因为内存不足无法启动；</li>
</ul>
<pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 改变设置</span>
sysctl -w vm.max_map_count<span class="token operator">=</span>262144
<span class="token comment" spellcheck="true"># 使之立即生效</span>
sysctl -p
</code></pre>
<ul>
<li>需要创建<code>/mydata/elasticsearch/data</code>目录并设置权限，否则会因为无权限访问而启动失败。</li>
</ul>
<pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 创建目录</span>
<span class="token function">mkdir</span> /mydata/elasticsearch/data/
<span class="token comment" spellcheck="true"># 创建并改变该目录权限</span>
<span class="token function">chmod</span> 777 /mydata/elasticsearch/data
</code></pre>
<h5 id="Nginx"><a href="#Nginx" class="headerlink" title="Nginx"></a><a target="_blank" rel="noopener" href="http://www.macrozheng.com/#/deploy/mall_deploy_docker_compose?id=nginx">Nginx</a></h5><p>需要拷贝nginx配置文件，否则挂载时会因为没有配置文件而启动失败。</p>
<pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true"># 创建目录之后将nginx.conf文件上传到该目录下面</span>
<span class="token function">mkdir</span> /mydata/nginx/
</code></pre>
<h5 id="Logstash"><a href="#Logstash" class="headerlink" title="Logstash"></a><a target="_blank" rel="noopener" href="http://www.macrozheng.com/#/deploy/mall_deploy_docker_compose?id=logstash">Logstash</a></h5><p>修改Logstash的配置文件<code>logstash.conf</code>中<code>output</code>节点下的Elasticsearch连接地址为<code>es:9200</code>。</p>
<pre class=" language-properties"><code class="language-properties"><span class="token attr-name">output</span> <span class="token attr-value">{</span>
<span class="token attr-name">  elasticsearch</span> <span class="token attr-value">{</span>
<span class="token attr-name">    hosts</span> <span class="token punctuation">=</span><span class="token attr-value">> "es:9200"</span>
<span class="token attr-name">    index</span> <span class="token punctuation">=</span><span class="token attr-value">> "mall-%{type}-%{+YYYY.MM.dd}"</span>
  }
}
</code></pre>
<p>创建<code>/mydata/logstash</code>目录，并将Logstash的配置文件<code>logstash.conf</code>拷贝到该目录。</p>
<pre class=" language-bash"><code class="language-bash"><span class="token function">mkdir</span> /mydata/logstash
</code></pre>
<h4 id="执行docker-compose-env-yml脚本"><a href="#执行docker-compose-env-yml脚本" class="headerlink" title="执行docker-compose-env.yml脚本"></a>执行docker-compose-env.yml脚本</h4><blockquote>
<p>将该文件上传的linux服务器上，执行docker-compose up命令即可启动mall所依赖的所有服务。</p>
</blockquote>
<pre class=" language-yaml"><code class="language-yaml"><span class="token key atrule">version</span><span class="token punctuation">:</span> <span class="token string">'3'</span>
<span class="token key atrule">services</span><span class="token punctuation">:</span>
  <span class="token key atrule">mysql</span><span class="token punctuation">:</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> mysql<span class="token punctuation">:</span><span class="token number">5.7</span>
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> mysql
    <span class="token key atrule">command</span><span class="token punctuation">:</span> mysqld <span class="token punctuation">-</span><span class="token punctuation">-</span>character<span class="token punctuation">-</span>set<span class="token punctuation">-</span>server=utf8mb4 <span class="token punctuation">-</span><span class="token punctuation">-</span>collation<span class="token punctuation">-</span>server=utf8mb4_unicode_ci
    <span class="token key atrule">restart</span><span class="token punctuation">:</span> always
    <span class="token key atrule">environment</span><span class="token punctuation">:</span>
      <span class="token key atrule">MYSQL_ROOT_PASSWORD</span><span class="token punctuation">:</span> root <span class="token comment" spellcheck="true">#设置root帐号密码</span>
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> 3306<span class="token punctuation">:</span><span class="token number">3306</span>
    <span class="token key atrule">volumes</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> /mydata/mysql/data/db<span class="token punctuation">:</span>/var/lib/mysql <span class="token comment" spellcheck="true">#数据文件挂载</span>
      <span class="token punctuation">-</span> /mydata/mysql/data/conf<span class="token punctuation">:</span>/etc/mysql/conf.d <span class="token comment" spellcheck="true">#配置文件挂载</span>
      <span class="token punctuation">-</span> /mydata/mysql/log<span class="token punctuation">:</span>/var/log/mysql <span class="token comment" spellcheck="true">#日志文件挂载</span>
  <span class="token key atrule">redis</span><span class="token punctuation">:</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> redis<span class="token punctuation">:</span><span class="token number">5</span>
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> redis
    <span class="token key atrule">command</span><span class="token punctuation">:</span> redis<span class="token punctuation">-</span>server <span class="token punctuation">-</span><span class="token punctuation">-</span>appendonly yes
    <span class="token key atrule">volumes</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> /mydata/redis/data<span class="token punctuation">:</span>/data <span class="token comment" spellcheck="true">#数据文件挂载</span>
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> 6379<span class="token punctuation">:</span><span class="token number">6379</span>
  <span class="token key atrule">nginx</span><span class="token punctuation">:</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx<span class="token punctuation">:</span><span class="token number">1.10</span>
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">volumes</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> /mydata/nginx/nginx.conf<span class="token punctuation">:</span>/etc/nginx/nginx.conf <span class="token comment" spellcheck="true">#配置文件挂载</span>
      <span class="token punctuation">-</span> /mydata/nginx/html<span class="token punctuation">:</span>/usr/share/nginx/html <span class="token comment" spellcheck="true">#静态资源根目录挂载</span>
      <span class="token punctuation">-</span> /mydata/nginx/log<span class="token punctuation">:</span>/var/log/nginx <span class="token comment" spellcheck="true">#日志文件挂载</span>
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token datetime number">80:80</span>
  <span class="token key atrule">rabbitmq</span><span class="token punctuation">:</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> rabbitmq<span class="token punctuation">:</span>3.7.15<span class="token punctuation">-</span>management
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> rabbitmq
    <span class="token key atrule">volumes</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> /mydata/rabbitmq/data<span class="token punctuation">:</span>/var/lib/rabbitmq <span class="token comment" spellcheck="true">#数据文件挂载</span>
      <span class="token punctuation">-</span> /mydata/rabbitmq/log<span class="token punctuation">:</span>/var/log/rabbitmq <span class="token comment" spellcheck="true">#日志文件挂载</span>
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> 5672<span class="token punctuation">:</span><span class="token number">5672</span>
      <span class="token punctuation">-</span> 15672<span class="token punctuation">:</span><span class="token number">15672</span>
  <span class="token key atrule">elasticsearch</span><span class="token punctuation">:</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> elasticsearch<span class="token punctuation">:</span>7.6.2
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> elasticsearch
    <span class="token key atrule">environment</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token string">"cluster.name=elasticsearch"</span> <span class="token comment" spellcheck="true">#设置集群名称为elasticsearch</span>
      <span class="token punctuation">-</span> <span class="token string">"discovery.type=single-node"</span> <span class="token comment" spellcheck="true">#以单一节点模式启动</span>
      <span class="token punctuation">-</span> <span class="token string">"ES_JAVA_OPTS=-Xms512m -Xmx512m"</span> <span class="token comment" spellcheck="true">#设置使用jvm内存大小</span>
    <span class="token key atrule">volumes</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> /mydata/elasticsearch/plugins<span class="token punctuation">:</span>/usr/share/elasticsearch/plugins <span class="token comment" spellcheck="true">#插件文件挂载</span>
      <span class="token punctuation">-</span> /mydata/elasticsearch/data<span class="token punctuation">:</span>/usr/share/elasticsearch/data <span class="token comment" spellcheck="true">#数据文件挂载</span>
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> 9200<span class="token punctuation">:</span><span class="token number">9200</span>
      <span class="token punctuation">-</span> 9300<span class="token punctuation">:</span><span class="token number">9300</span>
  <span class="token key atrule">logstash</span><span class="token punctuation">:</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> logstash<span class="token punctuation">:</span>7.6.2
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> logstash
    <span class="token key atrule">environment</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> TZ=Asia/Shanghai
    <span class="token key atrule">volumes</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> /mydata/logstash/logstash.conf<span class="token punctuation">:</span>/usr/share/logstash/pipeline/logstash.conf <span class="token comment" spellcheck="true">#挂载logstash的配置文件</span>
    <span class="token key atrule">depends_on</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> elasticsearch <span class="token comment" spellcheck="true">#kibana在elasticsearch启动之后再启动</span>
    <span class="token key atrule">links</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> elasticsearch<span class="token punctuation">:</span>es <span class="token comment" spellcheck="true">#可以用es这个域名访问elasticsearch服务</span>
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> 4560<span class="token punctuation">:</span><span class="token number">4560</span>
      <span class="token punctuation">-</span> 4561<span class="token punctuation">:</span><span class="token number">4561</span>
      <span class="token punctuation">-</span> 4562<span class="token punctuation">:</span><span class="token number">4562</span>
      <span class="token punctuation">-</span> 4563<span class="token punctuation">:</span><span class="token number">4563</span>
  <span class="token key atrule">kibana</span><span class="token punctuation">:</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> kibana<span class="token punctuation">:</span>7.6.2
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> kibana
    <span class="token key atrule">links</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> elasticsearch<span class="token punctuation">:</span>es <span class="token comment" spellcheck="true">#可以用es这个域名访问elasticsearch服务</span>
    <span class="token key atrule">depends_on</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> elasticsearch <span class="token comment" spellcheck="true">#kibana在elasticsearch启动之后再启动</span>
    <span class="token key atrule">environment</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token string">"elasticsearch.hosts=http://es:9200"</span> <span class="token comment" spellcheck="true">#设置访问elasticsearch的地址</span>
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> 5601<span class="token punctuation">:</span><span class="token number">5601</span>
  <span class="token key atrule">mongo</span><span class="token punctuation">:</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> mongo<span class="token punctuation">:</span>4.2.5
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> mongo
    <span class="token key atrule">volumes</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> /mydata/mongo/db<span class="token punctuation">:</span>/data/db <span class="token comment" spellcheck="true">#数据文件挂载</span>
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> 27017<span class="token punctuation">:</span><span class="token number">27017</span>
</code></pre>
<p>上传完后在当前目录下执行如下命令：</p>
<pre class=" language-bash"><code class="language-bash">docker-compose -f docker-compose-env.yml up -d
</code></pre>
<h4 id="对依赖服务进行以下设置"><a href="#对依赖服务进行以下设置" class="headerlink" title="对依赖服务进行以下设置"></a>对依赖服务进行以下设置</h4><p>当所有依赖服务启动完成后，需要对以下服务进行一些设置。</p>
<h5 id="mysql"><a href="#mysql" class="headerlink" title="mysql"></a>mysql</h5><blockquote>
<p>需要创建mall数据库并创建一个可以远程访问的对象reader。</p>
</blockquote>
<ul>
<li>将mall.sql文件拷贝到mysql容器的/目录下：</li>
</ul>
<pre class=" language-bash"><code class="language-bash">docker <span class="token function">cp</span> /mydata/mall.sql mysql:/
</code></pre>
<ul>
<li>进入mysql容器并执行如下操作：</li>
</ul>
<pre class=" language-bash"><code class="language-bash"><span class="token comment" spellcheck="true">#进入mysql容器</span>
docker <span class="token function">exec</span> -it mysql /bin/bash
<span class="token comment" spellcheck="true">#连接到mysql服务</span>
mysql -uroot -proot --default-character-set<span class="token operator">=</span>utf8
<span class="token comment" spellcheck="true">#创建远程访问用户</span>
grant all privileges on *.* to <span class="token string">'reader'</span> @<span class="token string">'%'</span> identified by <span class="token string">'123456'</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">#创建mall数据库</span>
create database mall character <span class="token keyword">set</span> utf8<span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">#使用mall数据库</span>
use mall<span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">#导入mall.sql脚本</span>
<span class="token function">source</span> /mall.sql<span class="token punctuation">;</span>
</code></pre>
<h5 id="elasticsearch"><a href="#elasticsearch" class="headerlink" title="elasticsearch"></a>elasticsearch</h5><blockquote>
<p>需要安装中文分词器IKAnalyzer，并重新启动。</p>
</blockquote>
<pre class=" language-bash"><code class="language-bash">docker <span class="token function">exec</span> -it elasticsearch /bin/bash
<span class="token comment" spellcheck="true">#此命令需要在容器中运行</span>
elasticsearch-plugin <span class="token function">install</span> https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.6.2/elasticsearch-analysis-ik-7.6.2.zip
docker restart elasticsearch
</code></pre>
<h5 id="logstash"><a href="#logstash" class="headerlink" title="logstash"></a>logstash</h5><blockquote>
<p>需要安装<code>json_lines</code>插件，并重新启动。</p>
</blockquote>
<pre class=" language-bash"><code class="language-bash">docker <span class="token function">exec</span> -it logstash /bin/bash
logstash-plugin <span class="token function">install</span> logstash-codec-json_lines
docker restart logstash
</code></pre>
<h5 id="rabbitmq"><a href="#rabbitmq" class="headerlink" title="rabbitmq"></a>rabbitmq</h5><blockquote>
<p>需要创建一个mall用户并设置虚拟host为/mall。</p>
</blockquote>
<ul>
<li><p>访问管理页面地址：<a target="_blank" rel="noopener" href="http://192.168.3.101:15672/">http://192.168.3.101:15672</a></p>
</li>
<li><p>输入账号密码并登录：guest guest</p>
</li>
<li><p>创建帐号并设置其角色为管理员：mall mall</p>
</li>
</ul>
<p><img src="https://notes2021.oss-cn-beijing.aliyuncs.com/2021/image-20220116113210563.png"></p>
<ul>
<li>创建一个新的虚拟host为：/mall</li>
</ul>
<p><img src="https://notes2021.oss-cn-beijing.aliyuncs.com/2021/image-20220116113425378.png"></p>
<ul>
<li>点击mall用户进入用户配置页面</li>
<li>给mall用户配置该虚拟host的权限</li>
</ul>
<p><img src="https://notes2021.oss-cn-beijing.aliyuncs.com/2021/image-20220116113617975.png"></p>
<h4 id="执行docker-compose-app-yml脚本"><a href="#执行docker-compose-app-yml脚本" class="headerlink" title="执行docker-compose-app.yml脚本"></a>执行docker-compose-app.yml脚本</h4><p>将该文件上传的linux服务器上，执行docker-compose up命令即可启动mall所有的应用。</p>
<p><img src="https://notes2021.oss-cn-beijing.aliyuncs.com/2021/image-20220116113741955.png"></p>
<blockquote>
<p>容器全部启动，内存占用情况：</p>
</blockquote>
<p><img src="https://notes2021.oss-cn-beijing.aliyuncs.com/2021/image-20220116113821591.png"></p>
<h4 id="开启防火墙即可在其他主机上访问所有服务"><a href="#开启防火墙即可在其他主机上访问所有服务" class="headerlink" title="开启防火墙即可在其他主机上访问所有服务"></a>开启防火墙即可在其他主机上访问所有服务</h4><pre class=" language-sh"><code class="language-sh">systemctl stop firewalld
</code></pre>
<h4 id="至此所有服务已经正常启动"><a href="#至此所有服务已经正常启动" class="headerlink" title="至此所有服务已经正常启动"></a>至此所有服务已经正常启动</h4><p><img src="https://notes2021.oss-cn-beijing.aliyuncs.com/2021/image-20220116114008607.png"></p>
<p><img src="https://notes2021.oss-cn-beijing.aliyuncs.com/2021/image-20220116114243627.png"></p>
<p><img src="https://notes2021.oss-cn-beijing.aliyuncs.com/2021/image-20220116115109582.png"></p>
<hr>








<h2 id="在Linux环境下的自动化部署（基于Jenkins容器）"><a href="#在Linux环境下的自动化部署（基于Jenkins容器）" class="headerlink" title="在Linux环境下的自动化部署（基于Jenkins容器）"></a>在Linux环境下的自动化部署（基于Jenkins容器）</h2><h2 id="mall前端项目的安装与部署"><a href="#mall前端项目的安装与部署" class="headerlink" title="mall前端项目的安装与部署"></a>mall前端项目的安装与部署</h2><blockquote>
<p>本文主要讲解mall前端项目mall-admin-web的在Windows和Linux环境下的安装及部署。</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://github.com/macrozheng/mall-admin-web">项目源码地址</a></p>
<h3 id="Windows下的安装及部署"><a href="#Windows下的安装及部署" class="headerlink" title="Windows下的安装及部署"></a>Windows下的安装及部署</h3><p>下载nodejs并安装</p>
<p>下载mall-admin-web的代码</p>
<p>从IDEA中打开mall-admin-web项目</p>
<p>打开控制台输入命令安装相关依赖</p>
<p>已经搭建了mall后台环境的启动</p>
<p>未搭建mall后台环境的启动</p>
<h3 id="Linux下的部署"><a href="#Linux下的部署" class="headerlink" title="Linux下的部署"></a>Linux下的部署</h3><ul>
<li><p>修改prod.env.js文件的配置</p>
</li>
<li><p>使用命令进行打包</p>
</li>
<li><p>打包后的代码位置</p>
</li>
<li><p>将dist目录打包为dist.tar.gz文件</p>
</li>
<li><p>Linux上nginx的安装可以参考<a target="_blank" rel="noopener" href="https://mp.weixin.qq.com/s/0fVMK107i5bBq8kGQqg8KA">mall在Linux环境下的部署（基于Docker容器）</a>中的nginx部分</p>
</li>
<li><p>将dist.tar.gz上传到linux服务器（nginx相关目录）</p>
</li>
<li><p>使用该命令进行解压操作</p>
</li>
<li><p>删除nginx的html文件夹</p>
</li>
<li><p>移动dist文件夹到html文件夹</p>
</li>
<li><p>运行mall-admin服务</p>
</li>
<li><p>重启nginx</p>
</li>
<li><p>访问首页并登录：<a target="_blank" rel="noopener" href="http://192.168.3.101/">http://192.168.3.101</a></p>
</li>
<li><p>发现调用的是Linux服务器地址</p>
</li>
</ul>
<hr>



<h2 id="mall-swarm在Windows环境下的部署"><a href="#mall-swarm在Windows环境下的部署" class="headerlink" title="mall-swarm在Windows环境下的部署"></a>mall-swarm在Windows环境下的部署</h2><h2 id="mall-swarm在Linux环境下的部署（基于Docker容器）"><a href="#mall-swarm在Linux环境下的部署（基于Docker容器）" class="headerlink" title="mall-swarm在Linux环境下的部署（基于Docker容器）"></a>mall-swarm在Linux环境下的部署（基于Docker容器）</h2><h2 id="微服务架构下的自动化部署，使用Jenkins来实现！"><a href="#微服务架构下的自动化部署，使用Jenkins来实现！" class="headerlink" title="微服务架构下的自动化部署，使用Jenkins来实现！"></a>微服务架构下的自动化部署，使用Jenkins来实现！</h2><h2 id="mall-swarm微服务项目在K8S下的实践！"><a href="#mall-swarm微服务项目在K8S下的实践！" class="headerlink" title="mall-swarm微服务项目在K8S下的实践！"></a>mall-swarm微服务项目在K8S下的实践！</h2><h2 id="常用的自动化部署技巧，贼好用，推荐给大家！"><a href="#常用的自动化部署技巧，贼好用，推荐给大家！" class="headerlink" title="常用的自动化部署技巧，贼好用，推荐给大家！"></a>常用的自动化部署技巧，贼好用，推荐给大家！</h2>
                
            </div>
            <hr/>

            

    <div class="reprint" id="reprint-statement">
        
            <div class="reprint__author">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-user">
                        文章作者:
                    </i>
                </span>
                <span class="reprint-info">
                    <a href="/about" rel="external nofollow noreferrer">Lemonade</a>
                </span>
            </div>
            <div class="reprint__type">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-link">
                        文章链接:
                    </i>
                </span>
                <span class="reprint-info">
                    <a href="http://101.42.229.218/2022/01/15/mall%E9%A1%B9%E7%9B%AE%E9%83%A8%E7%BD%B2/">http://101.42.229.218/2022/01/15/mall%E9%A1%B9%E7%9B%AE%E9%83%A8%E7%BD%B2/</a>
                </span>
            </div>
            <div class="reprint__notice">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-copyright">
                        版权声明:
                    </i>
                </span>
                <span class="reprint-info">
                    本博客所有文章除特別声明外，均采用
                    <a href="https://creativecommons.org/licenses/by/4.0/deed.zh" rel="external nofollow noreferrer" target="_blank">CC BY 4.0</a>
                    许可协议。转载请注明来源
                    <a href="/about" target="_blank">Lemonade</a>
                    !
                </span>
            </div>
        
    </div>

    <script async defer>
      document.addEventListener("copy", function (e) {
        let toastHTML = '<span>复制成功，请遵循本文的转载规则</span><button class="btn-flat toast-action" onclick="navToReprintStatement()" style="font-size: smaller">查看</a>';
        M.toast({html: toastHTML})
      });

      function navToReprintStatement() {
        $("html, body").animate({scrollTop: $("#reprint-statement").offset().top - 80}, 800);
      }
    </script>



            <div class="tag_share" style="display: block;">
                <div class="post-meta__tag-list" style="display: inline-block;">
                    
                        <div class="article-tag">
                            
                                <a href="/tags/%E9%A1%B9%E7%9B%AE%E4%B8%80/">
                                    <span class="chip bg-color">项目一</span>
                                </a>
                            
                        </div>
                    
                </div>
                <div class="post_share" style="zoom: 80%; width: fit-content; display: inline-block; float: right; margin: -0.15rem 0;">
                    <link rel="stylesheet" type="text/css" href="/libs/share/css/share.min.css">
<div id="article-share">

    
    <div class="social-share" data-sites="twitter,facebook,google,qq,qzone,wechat,weibo,douban,linkedin" data-wechat-qrcode-helper="<p>微信扫一扫即可分享！</p>"></div>
    <script src="/libs/share/js/social-share.min.js"></script>
    

    

</div>

                </div>
            </div>
            
                <style>
    #reward {
        margin: 40px 0;
        text-align: center;
    }

    #reward .reward-link {
        font-size: 1.4rem;
        line-height: 38px;
    }

    #reward .btn-floating:hover {
        box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2), 0 5px 15px rgba(0, 0, 0, 0.2);
    }

    #rewardModal {
        width: 320px;
        height: 350px;
    }

    #rewardModal .reward-title {
        margin: 15px auto;
        padding-bottom: 5px;
    }

    #rewardModal .modal-content {
        padding: 10px;
    }

    #rewardModal .close {
        position: absolute;
        right: 15px;
        top: 15px;
        color: rgba(0, 0, 0, 0.5);
        font-size: 1.3rem;
        line-height: 20px;
        cursor: pointer;
    }

    #rewardModal .close:hover {
        color: #ef5350;
        transform: scale(1.3);
        -moz-transform:scale(1.3);
        -webkit-transform:scale(1.3);
        -o-transform:scale(1.3);
    }

    #rewardModal .reward-tabs {
        margin: 0 auto;
        width: 210px;
    }

    .reward-tabs .tabs {
        height: 38px;
        margin: 10px auto;
        padding-left: 0;
    }

    .reward-content ul {
        padding-left: 0 !important;
    }

    .reward-tabs .tabs .tab {
        height: 38px;
        line-height: 38px;
    }

    .reward-tabs .tab a {
        color: #fff;
        background-color: #ccc;
    }

    .reward-tabs .tab a:hover {
        background-color: #ccc;
        color: #fff;
    }

    .reward-tabs .wechat-tab .active {
        color: #fff !important;
        background-color: #22AB38 !important;
    }

    .reward-tabs .alipay-tab .active {
        color: #fff !important;
        background-color: #019FE8 !important;
    }

    .reward-tabs .reward-img {
        width: 210px;
        height: 210px;
    }
</style>

<div id="reward">
    <a href="#rewardModal" class="reward-link modal-trigger btn-floating btn-medium waves-effect waves-light red">赏</a>

    <!-- Modal Structure -->
    <div id="rewardModal" class="modal">
        <div class="modal-content">
            <a class="close modal-close"><i class="fas fa-times"></i></a>
            <h4 class="reward-title">你的赏识是我前进的动力</h4>
            <div class="reward-content">
                <div class="reward-tabs">
                    <ul class="tabs row">
                        <li class="tab col s6 alipay-tab waves-effect waves-light"><a href="#alipay">支付宝</a></li>
                        <li class="tab col s6 wechat-tab waves-effect waves-light"><a href="#wechat">微 信</a></li>
                    </ul>
                    <div id="alipay">
                        <img src="/medias/reward/alipay.jpg" class="reward-img" alt="支付宝打赏二维码">
                    </div>
                    <div id="wechat">
                        <img src="/medias/reward/wechat.png" class="reward-img" alt="微信打赏二维码">
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<script>
    $(function () {
        $('.tabs').tabs();
    });
</script>

            
        </div>
    </div>

    

    

    

    

    

    

    

    

    

    

<article id="prenext-posts" class="prev-next articles">
    <div class="row article-row">
        
        <div class="article col s12 m6" data-aos="fade-up">
            <div class="article-badge left-badge text-color">
                <i class="fas fa-chevron-left"></i>&nbsp;上一篇</div>
            <div class="card">
                <a href="/2022/01/16/mall%E9%A1%B9%E7%9B%AE%E6%9E%B6%E6%9E%84-%E4%B8%9A%E5%8A%A1/">
                    <div class="card-image">
                        
                        
                        <img src="/medias/featureimages/2.jpg" class="responsive-img" alt="mall项目架构&amp;业务">
                        
                        <span class="card-title">mall项目架构&amp;业务</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            
                        
                    </div>
                    <div class="publish-info">
                        <span class="publish-date">
                            <i class="far fa-clock fa-fw icon-date"></i>2022-01-16
                        </span>
                        <span class="publish-author">
                            
                            <i class="fas fa-user fa-fw"></i>
                            Lemonade
                            
                        </span>
                    </div>
                </div>
                
            </div>
        </div>
        
        
        <div class="article col s12 m6" data-aos="fade-up">
            <div class="article-badge right-badge text-color">
                下一篇&nbsp;<i class="fas fa-chevron-right"></i>
            </div>
            <div class="card">
                <a href="/2022/01/12/mac%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE/">
                    <div class="card-image">
                        
                        
                        <img src="/medias/featureimages/20.jpg" class="responsive-img" alt="mac环境配置">
                        
                        <span class="card-title">mac环境配置</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            
                        
                    </div>
                    <div class="publish-info">
                            <span class="publish-date">
                                <i class="far fa-clock fa-fw icon-date"></i>2022-01-12
                            </span>
                        <span class="publish-author">
                            
                            <i class="fas fa-bookmark fa-fw icon-category"></i>
                            
                            <a href="/categories/5-%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE/" class="post-category">
                                    5.环境配置
                                </a>
                            
                            
                        </span>
                    </div>
                </div>
                
                <div class="card-action article-tags">
                    
                    <a href="/tags/mac/">
                        <span class="chip bg-color">mac</span>
                    </a>
                    
                    <a href="/tags/npm/">
                        <span class="chip bg-color">npm</span>
                    </a>
                    
                    <a href="/tags/Oracle/">
                        <span class="chip bg-color">Oracle</span>
                    </a>
                    
                </div>
                
            </div>
        </div>
        
    </div>
</article>

</div>



<!-- 代码块功能依赖 -->
<script type="text/javascript" src="/libs/codeBlock/codeBlockFuction.js"></script>

<!-- 代码语言 -->

<script type="text/javascript" src="/libs/codeBlock/codeLang.js"></script>


<!-- 代码块复制 -->

<script type="text/javascript" src="/libs/codeBlock/codeCopy.js"></script>


<!-- 代码块收缩 -->

<script type="text/javascript" src="/libs/codeBlock/codeShrink.js"></script>


    </div>
    <div id="toc-aside" class="expanded col l3 hide-on-med-and-down">
        <div class="toc-widget card" style="background-color: white;">
            <div class="toc-title"><i class="far fa-list-alt"></i>&nbsp;&nbsp;目录</div>
            <div id="toc-content"></div>
        </div>
    </div>
</div>

<!-- TOC 悬浮按钮. -->

<div id="floating-toc-btn" class="hide-on-med-and-down">
    <a class="btn-floating btn-large bg-color">
        <i class="fas fa-list-ul"></i>
    </a>
</div>


<script src="/libs/tocbot/tocbot.min.js"></script>
<script>
    $(function () {
        tocbot.init({
            tocSelector: '#toc-content',
            contentSelector: '#articleContent',
            headingsOffset: -($(window).height() * 0.4 - 45),
            collapseDepth: Number('0'),
            headingSelector: 'h2, h3, h4'
        });

        // modify the toc link href to support Chinese.
        let i = 0;
        let tocHeading = 'toc-heading-';
        $('#toc-content a').each(function () {
            $(this).attr('href', '#' + tocHeading + (++i));
        });

        // modify the heading title id to support Chinese.
        i = 0;
        $('#articleContent').children('h2, h3, h4').each(function () {
            $(this).attr('id', tocHeading + (++i));
        });

        // Set scroll toc fixed.
        let tocHeight = parseInt($(window).height() * 0.4 - 64);
        let $tocWidget = $('.toc-widget');
        $(window).scroll(function () {
            let scroll = $(window).scrollTop();
            /* add post toc fixed. */
            if (scroll > tocHeight) {
                $tocWidget.addClass('toc-fixed');
            } else {
                $tocWidget.removeClass('toc-fixed');
            }
        });

        
        /* 修复文章卡片 div 的宽度. */
        let fixPostCardWidth = function (srcId, targetId) {
            let srcDiv = $('#' + srcId);
            if (srcDiv.length === 0) {
                return;
            }

            let w = srcDiv.width();
            if (w >= 450) {
                w = w + 21;
            } else if (w >= 350 && w < 450) {
                w = w + 18;
            } else if (w >= 300 && w < 350) {
                w = w + 16;
            } else {
                w = w + 14;
            }
            $('#' + targetId).width(w);
        };

        // 切换TOC目录展开收缩的相关操作.
        const expandedClass = 'expanded';
        let $tocAside = $('#toc-aside');
        let $mainContent = $('#main-content');
        $('#floating-toc-btn .btn-floating').click(function () {
            if ($tocAside.hasClass(expandedClass)) {
                $tocAside.removeClass(expandedClass).hide();
                $mainContent.removeClass('l9');
            } else {
                $tocAside.addClass(expandedClass).show();
                $mainContent.addClass('l9');
            }
            fixPostCardWidth('artDetail', 'prenext-posts');
        });
        
    });
</script>

    

</main>




    <footer class="page-footer bg-color">
    
        <link rel="stylesheet" href="/libs/aplayer/APlayer.min.css">
<style>
    .aplayer .aplayer-lrc p {
        
        display: none;
        
        font-size: 12px;
        font-weight: 700;
        line-height: 16px !important;
    }

    .aplayer .aplayer-lrc p.aplayer-lrc-current {
        
        display: none;
        
        font-size: 15px;
        color: #42b983;
    }

    
    .aplayer.aplayer-fixed.aplayer-narrow .aplayer-body {
        left: -66px !important;
    }

    .aplayer.aplayer-fixed.aplayer-narrow .aplayer-body:hover {
        left: 0px !important;
    }

    
</style>
<div class="">
    
    <div class="row">
        <meting-js class="col l8 offset-l2 m10 offset-m1 s12"
                   server="netease"
                   type="playlist"
                   id="7141772781"
                   fixed='true'
                   autoplay='false'
                   theme='#42b983'
                   loop='all'
                   order='list'
                   preload='auto'
                   volume='0.7'
                   list-folded='false'
        >
        </meting-js>
    </div>
</div>

<script src="/libs/aplayer/APlayer.min.js"></script>
<script src="/libs/aplayer/Meting.min.js"></script>

    

    <div class="container row center-align"
         style="margin-bottom: 0px !important;">
        <div class="col s12 m8 l8 copy-right">
            Copyright&nbsp;&copy;
            
                <span id="year">2019-2022</span>
            
            <a href="/about" target="_blank">Lemonade</a>
            |&nbsp;Powered by&nbsp;<a href="https://hexo.io/" target="_blank">Hexo</a>
            |&nbsp;Theme&nbsp;<a href="https://github.com/blinkfox/hexo-theme-matery" target="_blank">Matery</a>
            <br>
            
                &nbsp;<i class="fas fa-chart-area"></i>&nbsp;站点总字数:&nbsp;<span
                        class="white-color">55.6k</span>
            
            
            
                
            
            
                <span id="busuanzi_container_site_pv">
                &nbsp;|&nbsp;<i class="far fa-eye"></i>&nbsp;总访问量:&nbsp;
                    <span id="busuanzi_value_site_pv" class="white-color"></span>
            </span>
            
            
                <span id="busuanzi_container_site_uv">
                &nbsp;|&nbsp;<i class="fas fa-users"></i>&nbsp;总访问人数:&nbsp;
                    <span id="busuanzi_value_site_uv" class="white-color"></span>
            </span>
            
            <br>

            <!-- 运行天数提醒. -->
            
            <br>
            
        </div>
        <div class="col s12 m4 l4 social-link social-statis">
    <a href="https://github.com/cat0501" class="tooltipped" target="_blank" data-tooltip="访问我的GitHub" data-position="top" data-delay="50">
        <i class="fab fa-github"></i>
    </a>



    <a href="https://blog.csdn.net/AC_872767407?spm=1001.2014.3001.5343" class="tooltipped" target="_blank" data-tooltip="关注我的CSDN: https://blog.csdn.net/AC_872767407?spm=1001.2014.3001.5343" data-position="top" data-delay="50">
        <i class="fab fa-csdn">C</i>
    </a>



    <a href="mailto:17782975312@163.com" class="tooltipped" target="_blank" data-tooltip="邮件联系我" data-position="top" data-delay="50">
        <i class="fas fa-envelope-open"></i>
    </a>







    <a href="tencent://AddContact/?fromId=50&fromSubId=1&subcmd=all&uin=872767407" class="tooltipped" target="_blank" data-tooltip="QQ联系我: 872767407" data-position="top" data-delay="50">
        <i class="fab fa-qq"></i>
    </a>







    <a href="/atom.xml" class="tooltipped" target="_blank" data-tooltip="RSS 订阅" data-position="top" data-delay="50">
        <i class="fas fa-rss"></i>
    </a>

</div>
    </div>
</footer>

<div class="progress-bar"></div>


    <!-- 搜索遮罩框 -->
<div id="searchModal" class="modal">
    <div class="modal-content">
        <div class="search-header">
            <span class="title"><i class="fas fa-search"></i>&nbsp;&nbsp;搜索</span>
            <input type="search" id="searchInput" name="s" placeholder="请输入搜索的关键字"
                   class="search-input">
        </div>
        <div id="searchResult"></div>
    </div>
</div>

<script type="text/javascript">
$(function () {
    var searchFunc = function (path, search_id, content_id) {
        'use strict';
        $.ajax({
            url: path,
            dataType: "xml",
            success: function (xmlResponse) {
                // get the contents from search data
                var datas = $("entry", xmlResponse).map(function () {
                    return {
                        title: $("title", this).text(),
                        content: $("content", this).text(),
                        url: $("url", this).text()
                    };
                }).get();
                var $input = document.getElementById(search_id);
                var $resultContent = document.getElementById(content_id);
                $input.addEventListener('input', function () {
                    var str = '<ul class=\"search-result-list\">';
                    var keywords = this.value.trim().toLowerCase().split(/[\s\-]+/);
                    $resultContent.innerHTML = "";
                    if (this.value.trim().length <= 0) {
                        return;
                    }
                    // perform local searching
                    datas.forEach(function (data) {
                        var isMatch = true;
                        var data_title = data.title.trim().toLowerCase();
                        var data_content = data.content.trim().replace(/<[^>]+>/g, "").toLowerCase();
                        var data_url = data.url;
                        data_url = data_url.indexOf('/') === 0 ? data.url : '/' + data_url;
                        var index_title = -1;
                        var index_content = -1;
                        var first_occur = -1;
                        // only match artiles with not empty titles and contents
                        if (data_title !== '' && data_content !== '') {
                            keywords.forEach(function (keyword, i) {
                                index_title = data_title.indexOf(keyword);
                                index_content = data_content.indexOf(keyword);
                                if (index_title < 0 && index_content < 0) {
                                    isMatch = false;
                                } else {
                                    if (index_content < 0) {
                                        index_content = 0;
                                    }
                                    if (i === 0) {
                                        first_occur = index_content;
                                    }
                                }
                            });
                        }
                        // show search results
                        if (isMatch) {
                            str += "<li><a href='" + data_url + "' class='search-result-title'>" + data_title + "</a>";
                            var content = data.content.trim().replace(/<[^>]+>/g, "");
                            if (first_occur >= 0) {
                                // cut out 100 characters
                                var start = first_occur - 20;
                                var end = first_occur + 80;
                                if (start < 0) {
                                    start = 0;
                                }
                                if (start === 0) {
                                    end = 100;
                                }
                                if (end > content.length) {
                                    end = content.length;
                                }
                                var match_content = content.substr(start, end);
                                // highlight all keywords
                                keywords.forEach(function (keyword) {
                                    var regS = new RegExp(keyword, "gi");
                                    match_content = match_content.replace(regS, "<em class=\"search-keyword\">" + keyword + "</em>");
                                });

                                str += "<p class=\"search-result\">" + match_content + "...</p>"
                            }
                            str += "</li>";
                        }
                    });
                    str += "</ul>";
                    $resultContent.innerHTML = str;
                });
            }
        });
    };

    searchFunc('/search.xml', 'searchInput', 'searchResult');
});
</script>

    <!-- 回到顶部按钮 -->
<div id="backTop" class="top-scroll">
    <a class="btn-floating btn-large waves-effect waves-light" href="#!">
        <i class="fas fa-arrow-up"></i>
    </a>
</div>


    <script src="/libs/materialize/materialize.min.js"></script>
    <script src="/libs/masonry/masonry.pkgd.min.js"></script>
    <script src="/libs/aos/aos.js"></script>
    <script src="/libs/scrollprogress/scrollProgress.min.js"></script>
    <script src="/libs/lightGallery/js/lightgallery-all.min.js"></script>
    <script src="/js/matery.js"></script>

    

    

    <!-- 雪花特效 -->
    

    <!-- 鼠标星星特效 -->
    

     
        <script src="https://ssl.captcha.qq.com/TCaptcha.js"></script>
        <script src="/libs/others/TencentCaptcha.js"></script>
        <button id="TencentCaptcha" data-appid="xxxxxxxxxx" data-cbfn="callback" type="button" hidden></button>
    

    <!-- Baidu Analytics -->

    <!-- Baidu Push -->

<script>
    (function () {
        var bp = document.createElement('script');
        var curProtocol = window.location.protocol.split(':')[0];
        if (curProtocol === 'https') {
            bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
        } else {
            bp.src = 'http://push.zhanzhang.baidu.com/push.js';
        }
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(bp, s);
    })();
</script>

    
    <script src="/libs/others/clicklove.js" async="async"></script>
    
    
    <script async src="/libs/others/busuanzi.pure.mini.js"></script>
    

    

    

    <!--腾讯兔小巢-->
    
    

    
    
    <script type="text/javascript" size="150" alpha='0.6'
        zIndex="-1" src="/libs/background/ribbon-refresh.min.js" async="async"></script>
    

    
    <script type="text/javascript" src="/libs/background/ribbon-dynamic.js" async="async"></script>
    

    
    <script src="/libs/instantpage/instantpage.js" type="module"></script>
    

    
    <script type="text/javascript">
        //只在桌面版网页启用特效
        var windowWidth = $(window).width();
        if (windowWidth > 768) {
            document.write('<script type="text/javascript" src="/js/sakura.js"><\/script>');
        }
    </script>
        

</body>

</html>
